package jp.tkym.labs.store;

import jp.tkym.labs.store.api.BeanIs;
import jp.tkym.labs.store.api.BeanStore;
import jp.tkym.labs.store.api.EntityConfigProvider;
import jp.tkym.labs.store.api.EntityConfigProvider.EntityConfig;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;

class GoogleBeanStore<B> implements BeanStore<B> {
	private EntityResolver<B> resolver;
	private DatastoreService datastoreService;
	
	GoogleBeanStore(DatastoreService datastoreService, Class<B> cls,
			Key parent) {
		this.datastoreService = datastoreService;
		EntityConfig config = EntityConfigProvider.getInstance().get(cls);
		resolver = new EntityResolver<B>(cls, parent,
				config.getKeyProperty());
		for(String propertyName : config.indexedProperties())
			resolver.addIndexedProperty(propertyName);
	}

	GoogleBeanStore(DatastoreService datastoreService, Class<B> cls) {
		this(datastoreService, cls, null);
	}

	@Override
	public BeanIs<B> is(B bean) {
		return new GoogleBeanIs<B>(datastoreService, resolver.toKey(bean));
	}

	@Override
	public BeanIs<B> is(long id) {
		return new GoogleBeanIs<B>(datastoreService, resolver.toKey(id));
	}

	@Override
	public BeanIs<B> is(String name) {
		return new GoogleBeanIs<B>(datastoreService, resolver.toKey(name));
	}

	@Override
	public void put(B bean) {
		Key key = datastoreService.put(resolver.toEntity(bean));
		resolver.toBeanFromKey(bean, key);
	}

	@Override
	public void remove(long id) {
		datastoreService.delete(resolver.toKey(id));
	}

	@Override
	public void remove(String name) {
		datastoreService.delete(resolver.toKey(name));
	}

	@Override
	public B get(long id) {
		return get(resolver.toKey(id));
	}

	@Override
	public B get(String key) {
		return get(resolver.toKey(key));
	}

	private B get(Key key) {
		try {
			Entity entity = datastoreService.get(key);
			return resolver.toBean(entity);
		} catch (EntityNotFoundException e) {
			return null;
		}
	}
}